﻿using Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;

namespace Business
{
    public class DeliveryBiz
    {
        ILogger logger = new Logger();

        private bool IsReceived = false;

        public int SaveItem(Delivery item)
        {
            item.DeliveryNo = GetDeliveryNumber();
            var dbContext = new Context();

            dbContext.Deliveries.Add(item);
            dbContext.SaveChanges();

            return item.Id;
        }

        public void UpdateItem(Delivery item)
        {
            var dbContext = new Context();
            dbContext.Entry(item).State = EntityState.Modified;
            dbContext.SaveChanges();
        }

        public Delivery LoadItem(int id)
        {
            var dbContext = new Context();
            return (from item in dbContext.Deliveries
                    where item.Id == id
                    select item).First();
        }

        public void RemoveItem(List<Delivery> items)
        {
            var dbContext = new Context();

            string ids = string.Empty;

            foreach (var item in items)
            {
                ids += item.Id + ",";
            }

            if (ids.EndsWith(","))
            {
                ids = ids.Substring(0, ids.Length-1);

                string deleteChildCommand = string.Format(Constants.DeleteChildCommand, "DeliveryDetail", "DeliveryId", ids);
                dbContext.Database.ExecuteSqlCommand(deleteChildCommand);

                string deleteCommand = string.Format(Constants.DeleteCommand, "[Delivery]", ids);
                dbContext.Database.ExecuteSqlCommand(deleteCommand);
            }            
        }

        public void RemoveSingleItem(int id)
        {
            var dbContext = new Context();
            string deleteChildCommand = string.Format(Constants.DeleteChildCommand, "DeliveryDetail", "DeliveryId", id);
            dbContext.Database.ExecuteSqlCommand(deleteChildCommand);

            string deleteCommand = string.Format(Constants.DeleteCommand, "[Delivery]", id);
            dbContext.Database.ExecuteSqlCommand(deleteCommand);
        }
        
        public List<Delivery> LoadItems()
        {
            var dbContext = new Context();
            return (from item in dbContext.Deliveries
                    orderby item.DeliveryNo
                    select item).ToList();
        }

        private string GetDeliveryNumber()
        {
            return "GH_" + DateTime.Now.ToString("ddMMyyyy_hhmm");
        }

        public DeliveryStatus SendSms(int id, string currentUser)
        {
            DeliveryStatus status = new DeliveryStatus();

            var configBiz = new ConfigurationBiz();
            var smsConfig = configBiz.GetSmsConfiguration();

            if(smsConfig == null)
            {
                throw new Exception(Constants.MessageSmsConfigError);
            }

            SerialPort port = null;
            SmsHelper.Helper smsHelper = new SmsHelper.Helper();

            try
            {
                port = new SerialPort(smsConfig.PortName);

                port.BaudRate = smsConfig.BaudRate;
                port.Parity = Parity.None;
                port.StopBits = StopBits.One;
                port.DataBits = smsConfig.DataBits;
                port.Handshake = Handshake.None;
                port.RtsEnable = true;
                port.Open();

                port.DataReceived += port_DataReceived;

                if (!port.IsOpen) throw new Exception("Cannot access to port " + smsConfig.PortName);

                #region Load Templates
                var biz = new SmsBiz();
                var templates = biz.LoadItems();
                Sms smsInternal1 = null;
                Sms smsInternal2 = null;
                Sms smsExternal = null;

                string mobile = string.Empty;

                foreach (var template in templates)
                {
                    if (string.Equals(template.Name, Constants.SmsDeliveryInternal1, StringComparison.InvariantCultureIgnoreCase))
                    {
                        smsInternal1 = template;
                    }

                    if (string.Equals(template.Name, Constants.SmsDeliveryInternal2, StringComparison.InvariantCultureIgnoreCase))
                    {
                        smsInternal2 = template;
                    }

                    if (string.Equals(template.Name, Constants.SmsDeliveryExternal, StringComparison.InvariantCultureIgnoreCase))
                    {
                        smsExternal = template;
                    }
                }
                #endregion

                var item = LoadItem(id);
                int time = 0;
                int numberSuccess = 0;
                string customerName = string.Empty;

                bool isFirstTime = true;
                var orderBiz = new OrderBiz();

                foreach (var detail in item.Details)
                {
                    if (detail.Order != null && string.Equals(detail.Order.SendMessage, Constants.DeliverySentSms, StringComparison.InvariantCultureIgnoreCase))
                    {
                        numberSuccess++;
                        continue;
                    }

                    if (!isFirstTime)
                    {
                        Thread.Sleep(5000);
                    }

                    customerName = string.Empty;
                    mobile = string.Empty;
                    string content = string.Empty;
                    try
                    {
                        if (detail.Order.DeliveryInternal)
                        {
                            if (!string.IsNullOrEmpty(detail.Order.Recipient))
                            {
                                // Send direct
                                content = smsInternal1.Content;
                                mobile = detail.Order.RecipientPhone;
                                customerName = detail.Order.Recipient;
                                
                                if (!string.IsNullOrEmpty(mobile))
                                {
                                    time += detail.Time;
                                    content = content.Replace(Constants.SmsParameter1, customerName);
                                    content = content.Replace(Constants.SmsParameter2, item.Staff.Mobile);
                                    content = content.Replace(Constants.SmsParameter3, Utility.ConvertTime(time));

                                    SendMessage(port, mobile, content, 500);
                                    orderBiz.UpdateSmsStatus(detail.Order.Id, Constants.DeliverySentSms);
                                    isFirstTime = false;
                                    numberSuccess++;

                                    var smsDataBiz = new SmsDataBiz();
                                    var smsData = new SmsData();
                                    smsData.SendFrom = currentUser;
                                    smsData.SendOn = DateTime.Now;
                                    smsData.SendTo = customerName;
                                    smsData.SendToNumber = mobile;
                                    smsData.Content = content;
                                    smsDataBiz.SaveItem(smsData);
                                }
                                else
                                {
                                    var customer = detail.Order.Customer;
                                    status.Error = string.Format("Đơn hàng {3}: Không gửi được sms cho khách hàng {0} do không có số điện thoại. {1}{2}",
                                        customerName, Environment.NewLine, status.Error, detail.Order.OrderNo); 
                                }
                            }
                            else
                            {
                                // Send direct
                                content = smsInternal1.Content;
                                mobile = detail.Order.Customer.Mobile1;
                                customerName = detail.Order.Customer.SMS;

                                if (!string.IsNullOrEmpty(mobile))
                                {
                                    time += detail.Time;
                                    content = content.Replace(Constants.SmsParameter1, customerName);
                                    content = content.Replace(Constants.SmsParameter2, item.Staff.Mobile);
                                    content = content.Replace(Constants.SmsParameter3, Utility.ConvertTime(time));

                                    SendMessage(port, mobile, content, 500);
                                    orderBiz.UpdateSmsStatus(detail.Order.Id, Constants.DeliverySentSms);
                                    isFirstTime = false;
                                    numberSuccess++;

                                    var smsDataBiz = new SmsDataBiz();
                                    var smsData = new SmsData();
                                    smsData.SendFrom = currentUser;
                                    smsData.SendOn = DateTime.Now;
                                    smsData.SendTo = customerName;
                                    smsData.SendToNumber = mobile;
                                    smsData.Content = content;
                                    smsDataBiz.SaveItem(smsData);
                                }
                                else
                                {
                                    var customer = detail.Order.Customer;
                                    status.Error = string.Format("Đơn hàng {3}: Không gửi được sms cho khách hàng {0} do không có số điện thoại. {1}{2}",
                                        customerName, Environment.NewLine, status.Error, detail.Order.OrderNo);
                                }
                            }
                        }
                        else
                        {
                            // Send direct external
                            content = smsExternal.Content;
                            mobile = detail.Order.Customer.Mobile1;
                            customerName = detail.Order.Customer.SMS;

                            if (!string.IsNullOrEmpty(mobile))
                            {
                                content = content.Replace(Constants.SmsParameter1, customerName);
                                content = content.Replace(Constants.SmsParameter3, Utility.ConvertTime(DateTime.Now));

                                SendMessage(port, mobile, content, 500);
                                orderBiz.UpdateSmsStatus(detail.Order.Id, Constants.DeliverySentSms);
                                isFirstTime = false;
                                numberSuccess++;

                                var smsDataBiz = new SmsDataBiz();
                                var smsData = new SmsData();
                                smsData.SendFrom = currentUser;
                                smsData.SendOn = DateTime.Now;
                                smsData.SendTo = customerName;
                                smsData.SendToNumber = mobile;
                                smsData.Content = content;
                                smsDataBiz.SaveItem(smsData);
                            }
                            else
                            {
                                var customer = detail.Order.Customer;
                                status.Error = string.Format("Đơn hàng {3}: Không gửi được sms cho khách hàng {0} do không có số điện thoại. {1}{2}",
                                    customerName, Environment.NewLine, status.Error, detail.Order.OrderNo);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if (detail.Order == null)
                        {
                            status.Error = string.Concat("Không tìm thấy thông tin đơn hàng có ID: ", detail.OrderId, Environment.NewLine, status.Error);
                        }
                        else
                        {
                            if (detail.Order.Customer == null)
                            {
                                status.Error = string.Concat("Không tìm thấy thông tin khách hàng của đơn hàng: ", detail.Order.OrderNo, Environment.NewLine, status.Error);
                            }
                            else
                            {
                                var customer = detail.Order.Customer;
                                status.Error = string.Format("Đơn hàng {4}: Không gửi được sms cho khách hàng {0} có số điện thoại: {1}. {2}{3}",
                                    customerName, mobile, Environment.NewLine, status.Error, detail.Order.OrderNo);                                
                            }
                        }
                        logger.LogException(ex);
                    }                    
                }

                if (numberSuccess == item.Details.Count)
                {
                    status.Status = Constants.DeliverySentSms;
                }
                else
                {
                    status.Status = string.Format("{0} ({1}/{2})", Constants.DeliverySentSms, numberSuccess, item.Details.Count);
                }
            }
            catch(Exception ex)
            {
                throw new Exception(Constants.MessageSmsConfigError);
            }
            finally
            {
                if(port != null)
                {
                    smsHelper.ClosePort(port);
                }
            }

            return status;
        }

        void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            IsReceived = true;
        }

        public DeliveryStatus SendEmail(int id, string currentUser)
        {
            DeliveryStatus status = new DeliveryStatus();

            var biz = new EmailBiz();
            var template = biz.LoadItem(Constants.EmailDelivery);

            if(template == null)
            {
                throw new Exception(Constants.MessageEmailNotExistError);
            }

            var item = LoadItem(id);

            int numberSuccess = 0;

            var orderBiz = new OrderBiz();

            foreach(var detail in item.Details)
            {
                if (detail.Order != null && string.Equals(detail.Order.SendEmail, Constants.DeliverySentEmail, StringComparison.InvariantCultureIgnoreCase))
                {
                    numberSuccess++;
                    continue;
                }

                try
                {
                    List<string> to = new List<string>();
                    string content = string.Empty;
                    string subject = string.Empty;

                    content = template.Content;
                    subject = template.Subject;

                    subject = subject.Replace(Constants.EmailParameter4, detail.Order.OrderNo);

                    string email = detail.Order.Customer.Email1;
                    string email2 = detail.Order.Customer.Email2;

                    if (!string.IsNullOrEmpty(email) && !to.Contains(email))
                    {
                        to.Add(email);
                    }

                    if (!string.IsNullOrEmpty(email2) && !to.Contains(email2))
                    {
                        to.Add(email2);
                    }

                    if (to.Count > 0)
                    {
                        string details = GetDetails(detail.Order);

                        content = content.Replace(Constants.EmailParameter1, detail.Order.Customer.SMS);
                        content = content.Replace(Constants.EmailParameter2, details);
                        content = content.Replace(Constants.EmailParameter3, Constants.EmailNewLine);

                        var helper = new EmailHelper();
                        helper.SendEmail(to, null, subject, content, currentUser);                        
                        numberSuccess++;

                        orderBiz.UpdateEmailStatus(detail.Order.Id, Constants.DeliverySentEmail);
                    }
                    else
                    {
                        var customer = detail.Order.Customer;
                        status.Error = string.Format("Đơn hàng {3}: Khách hàng {0} không có địa chỉ email. {1}{2}",
                            customer.FullName, Environment.NewLine, status.Error, detail.Order.OrderNo);
                    }
                }
                catch(Exception ex)
                {
                    if (detail.Order == null)
                    {
                        status.Error = string.Concat("Không tìm thấy thông tin đơn hàng có ID: ", detail.OrderId, Environment.NewLine, status.Error);
                    }
                    else
                    {
                        if (detail.Order.Customer == null)
                        {
                            status.Error = string.Concat("Không tìm thấy thông tin khách hàng của đơn hàng: ", detail.Order.OrderNo, Environment.NewLine, status.Error);
                        }
                        else
                        {
                            var customer = detail.Order.Customer;
                            status.Error = string.Format("Đơn hàng {5}: Không gửi được email cho khách hàng {0} có địa chỉ email: {1}, {2}. {3}{4}",
                                customer.FullName, customer.Email1, customer.Email2, Environment.NewLine, status.Error, detail.Order.OrderNo);
                        }
                    }
                    
                }
            }

            if (numberSuccess == item.Details.Count)
            {
                status.Status = Constants.DeliverySentEmail;
            }
            else
            {
                status.Status = string.Format("{0} ({1}/{2})", Constants.DeliverySentEmail, numberSuccess, item.Details.Count);
            }

            return status;
        }

        public void UpdateEmailStatus(int id, string status)
        {
            var dbContext = new Context();

            Delivery delivery = (from item in dbContext.Deliveries
                                 where item.Id == id
                                 select item).First();

            if (delivery != null)
            {
                delivery.IsSendEmail = status;

                dbContext.Entry(delivery).State = EntityState.Modified;
                dbContext.SaveChanges();

                var details = delivery.Details;
                if(details != null && details.Count > 0)
                {
                    foreach(var detail in details)
                    {
                        var order = detail.Order;
                        order.Status = Constants.OrderStatusDelivering;
                        dbContext.Entry(order).State = EntityState.Modified;
                        dbContext.SaveChanges();
                    }
                }
            }            
        }

        public void UpdateSmsStatus(int id, string status)
        {
            var dbContext = new Context();

            Delivery delivery = (from item in dbContext.Deliveries
                                 where item.Id == id
                                 select item).First();

            if (delivery != null)
            {
                delivery.IsSendSms = status;

                dbContext.Entry(delivery).State = EntityState.Modified;
                dbContext.SaveChanges();

                var details = delivery.Details;
                if (details != null && details.Count > 0)
                {
                    foreach (var detail in details)
                    {
                        var order = detail.Order;
                        order.Status = Constants.OrderStatusDelivering;
                        dbContext.Entry(order).State = EntityState.Modified;
                        dbContext.SaveChanges();
                    }
                }
            }
        }

        public void UpdateStatus(int id, string status)
        {
            var dbContext = new Context();

            Delivery delivery = (from item in dbContext.Deliveries
                                 where item.Id == id
                                 select item).First();

            if (delivery != null)
            {
                delivery.Status = status;

                dbContext.Entry(delivery).State = EntityState.Modified;
                dbContext.SaveChanges();
            }

            var idParam = new SqlParameter { ParameterName = "@DeliveryId", Value = DBNull.Value, DbType = DbType.Int32 };
            idParam.Value = id;            

            dbContext.Database.ExecuteSqlCommand("UpdateOrderStatus @DeliveryId", idParam);
        }

        private string GetDetails(Order order)
        {
            if (order.Details == null || order.Details.Count == 0) return string.Empty;

            StringBuilder content = new StringBuilder();

            content.Append("<table width='100%' cellpadding='0' cellspacing='0' >");
            content.Append("<colgroup>");
            content.Append("<col width='25%' />");
            content.Append("<col width='25%' />");
            content.Append("<col width='25%' />");
            content.Append("<col width='25%' />");
            content.Append("</colgroup>");

            content.Append("<tr style='background: #002060; color: white; text-transform: uppercase;'>");
            content.Append("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5;border-left: 1px solid #D5D5D5; line-height: 25px; text-align: center;'>Tên mặt hàng</td>");
            content.Append("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Số lượng <label style='text-transform: lowercase;'>(m)</label></td>");
            content.Append("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Đơn giá (VNĐ)</td>");
            content.Append("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Tổng (VNĐ)</td>");
            content.Append("</tr>");

            decimal total = 0;
            decimal vat = 0;
            decimal final = 0;
            decimal totalLd = 0;

            var hash = GetOrderDetailByProductType(order);

            foreach (var key in hash.Keys)
            {
                var data = hash[key] as List<OrderDetail>;

                content.Append("<tr>");
                content.Append("<td colspan='4' style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-bottom: 0px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: left; padding: 0 10px;'>");
                content.Append(key);
                content.Append("</td>");
                content.Append("</tr>");

                foreach (var detail in data)
                {
                    content.Append("<tr>");
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5;border-left: 1px solid #D5D5D5; line-height: 25px; text-align: left; padding: 0 10px;'>{0}</td>", detail.Product.Name));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.Quantity));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.ProductActualPrice.Value.ToString(Constants.CurrencyFormat)));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.Total.ToString(Constants.CurrencyFormat)));
                    content.Append("</tr>");

                    total += detail.Total;
                }
            }

            if (total > 0)
            {
                if (order.Vat)
                {
                    content.Append("<tr>");
                    content.Append("<td colspan='3' style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Tổng đã bao gồm VAT(VNĐ)</td>");
                    content.Append(string.Format("<td style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 0px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", total.ToString(Constants.CurrencyFormat)));
                    content.Append("</tr>");
                }
                else
                {
                    content.Append("<tr>");
                    content.Append("<td colspan='3' style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Tổng không bao gồm VAT(VNĐ)</td>");
                    content.Append(string.Format("<td style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 0px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", total.ToString(Constants.CurrencyFormat)));
                    content.Append("</tr>");
                }
            }

            var itemLd = GetLd(order);
            if (itemLd.Count > 0)
            {
                content.Append("<tr>");
                content.Append("<td colspan='4' style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-bottom: 0px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: left; padding: 0 10px;'>");
                content.Append("Hàng LD");
                content.Append("</td>");
                content.Append("</tr>");

                foreach (var detail in itemLd)
                {
                    content.Append("<tr>");
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5;border-left: 1px solid #D5D5D5; line-height: 25px; text-align: left; padding: 0 10px;'>{0}</td>", detail.ProductLD.Name));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.Quantity));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.ProductActualPrice.Value.ToString(Constants.CurrencyFormat)));
                    content.Append(string.Format("<td style='border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", detail.Total.ToString(Constants.CurrencyFormat)));
                    content.Append("</tr>");

                    totalLd += detail.Total;
                }
            }

            if (totalLd > 0)
            {
                content.Append("<tr>");
                content.Append("<td colspan='3' style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Tổng (VNĐ)</td>");
                content.Append(string.Format("<td style='font-weight: bold; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 0px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", totalLd.ToString(Constants.CurrencyFormat)));
                content.Append("</tr>");
            }

            final = total + vat + totalLd;

            if (final > 0)
            {
                content.Append("<tr>");
                content.Append("<td colspan='3' style='font-weight: bold; border-bottom: 1px solid #D5D5D5; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 1px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>Tổng tiền thanh toán(VNĐ)</td>");
                content.Append(string.Format("<td style='font-weight: bold; border-bottom: 1px solid #D5D5D5; border-top: 1px solid #D5D5D5;border-right: 1px solid #D5D5D5; border-left: 0px solid #D5D5D5; line-height: 25px; text-align: right; padding: 0 10px;'>{0}</td>", final.ToString(Constants.CurrencyFormat)));
                content.Append("</tr>");
                content.Append("</table>");
            }

            if (order.SendWithEmail && order.Liability.HasValue && order.Liability.Value > 0)
            {
                content.Append("<br />");
                content.Append("Dư nợ hiện tại: ");
                content.Append("<font color='Red'>");
                content.Append(order.Liability.Value.ToString(Constants.CurrencyFormat));
                content.Append(" VND");
                content.Append("</font>");
                content.Append("<br />");

                content.Append("Tổng dư nợ: ");
                content.Append("<font color='Red'>");
                content.Append((final + order.Liability.Value).ToString(Constants.CurrencyFormat));
                content.Append(" VND");
                content.Append("</font>");
            }

            return content.ToString();
        }

        private void SendMessage(SerialPort port, string number, string content, int timeOut)
        {
            string result = string.Empty;
            string command = string.Empty;

            // AT
            IsReceived = false;
            port.WriteLine("AT\r");
            ReceiveData(port, timeOut, "AT");

            // AT+CMGF=0
            IsReceived = false;
            port.WriteLine("AT+CMGF=0\r");
            ReceiveData(port, timeOut, "AT+CMGF=0");

            int dataLength = 0;
            string messsage = EncodePdu.GetPdu(number, content, "+8491020005", out dataLength);

            // AT+CMGS=dataLength
            command = string.Format("AT+CMGS={0}\r", dataLength);
            IsReceived = false;
            port.WriteLine(command);
            ReceiveData(port, timeOut, command);

            // content
            command = messsage + char.ConvertFromUtf32(26) + "\r";
            IsReceived = false;
            port.WriteLine(command);
            ReceiveData(port, timeOut * 2, command);            
        }

        private void ReceiveData(SerialPort port, int timeOut, string command)
        {
            Thread.Sleep(timeOut);

            if (IsReceived)
            {
                string indata = port.ReadExisting();

                logger.LogInfoMessage("Delivery Message Result: " + indata);

                if (indata.ToUpper().Contains("ERROR"))
                {
                    throw new Exception("Error when send message: [Command]-" + command);
                }
            }
        }

        public List<DeliveryTemplate> GetTemplateData()
        {
            var context = new Context();
            return context.Database.SqlQuery<DeliveryTemplate>("GetDeliveryTemplate").ToList();
        }

        private Hashtable GetOrderDetailByProductType(Order order)
        {
            var hash = new Hashtable();
            var list = new List<OrderDetail>();

            foreach (var detail in order.Details)
            {
                if (detail.ProductId.HasValue)
                {
                    var type = detail.Product.TypeValue;
                    if (!hash.Contains(type))
                    {
                        list = new List<OrderDetail>();
                        list.Add(detail);
                        hash.Add(type, list);
                    }
                    else
                    {
                        list = hash[type] as List<OrderDetail>;
                        if (list == null)
                        {
                            list = new List<OrderDetail>();
                        }
                        list.Add(detail);
                        hash[type] = list;
                    }
                }
            }

            return hash;
        }

        private List<OrderDetail> GetLd(Order order)
        {
            var result = new List<OrderDetail>();

            foreach (var item in order.Details)
            {
                if (item.ProductLdId.HasValue)
                {
                    result.Add(item);
                }
            }

            return result;
        }
    }
}
